"""A server that keeps track of game scores.

Requires:
  Pyro: http://pyro.sourceforge.net/

Soon to require:
  Chart Director: http://www.advsofteng.com/
  CherryPy:       http://www.cherrypy.org/
"""

# TODO: Figure out how to do locking in Python.

import Pyro.core
import pickle
from player import Player

class PlayerScores:
  def __init__(self, name):
    self.wins = 0
    self.losses = 0
    self.max_score = 0
    self.name = name

  def __str__(self):
    num_games = self.wins + self.losses
    return "%s has won %.2f%% of %d games.  Max score is %d." % (
        self.name, self.wins * 100.0 / num_games, num_games, self.max_score)

class ScoreServer(Pyro.core.ObjBase):
  def __init__(self):
    Pyro.core.ObjBase.__init__(self)
    self.scores = {}

  def RegisterGameOutcome(self, players):
    """Expects a list of (player, score) tuples sorted by decreasing score."""
    assert(len(players) > 1)

    for player, score in players:
      if not self.scores.has_key(player.name):
        self.scores[player.name] = PlayerScores(player.name)

    i = 0
    for player, score in players:
      if not i:
        self.IncrementPlayer(player.name, 1, score)
      else:
        self.IncrementPlayer(player.name, -1, score)
      i += 1

    print "Logged stats for [%s]." % (" vs. ".join([p.name for p,s in players]))

  def IncrementPlayer(self, name, inc, score):
    score_struct = self.scores[name]
    if inc > 0:
      score_struct.wins += 1
    else:
      score_struct.losses += 1
    score_struct.max_score = max(score, score_struct.max_score)

if __name__ == "__main__":
  s = ScoreServer()

  # First see if there's a saved state file.
  try:
    state_file = open("state_file", "rb")
    s.scores = pickle.load(state_file)
    print "Loaded state from state file."
  except IOError:
    print "No state file found."

  Pyro.core.initServer()
  daemon = Pyro.core.Daemon()
  uri = daemon.connect(s, "scoreserver")

  print "Server running on port %d" % daemon.port
  print "Our object's URI is %s" % uri

  try:
    daemon.requestLoop()
  except KeyboardInterrupt:
    print "Final Tally:"
    for name, score in s.scores.iteritems():
      print str(score)

    # Save state.
    state_file = open("state_file", "wb")
    pickle.dump(s.scores, state_file)
  daemon.shutdown()
